/**
 * @ProjectName: 
 * @Copyright: 2014 lisheng  All Right Reserved.
 * @address: toughheart@163.com
 * @date: 2016年4月28日 下午10:23:35
 * @Description: 本内容未经本人允许禁止使用、转发.
 */

package com.ls.fw.web.file.support.config;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.ServletContextAware;

import com.ls.fw.commons.config.utils.PropertyUtil;
import com.ls.fw.commons.core.unit.SizeValue;
import com.ls.fw.commons.core.utils.file.FileUtil;
import com.ls.fw.web.core.servlet.utils.HttpUtils;
import com.ls.fw.web.file.constant.Global;

/**
 * 
 * @author lisheng
 * @date 2016年4月28日 下午10:23:35
 * @version V1.0
 */
public class DefaultFileConfiguration implements IFileConfiguration,
ServletContextAware {
	protected Logger logger = LoggerFactory.getLogger(this.getClass());

	private String configFilePath = "/config/file/file.properties";

	private static final LinkedHashMap<String, String> configInfo = new LinkedHashMap<String, String>();

	protected String baseUrl = "";
	// 顶级目录路径
	protected String rootDir = "";
	// 文件保存顶级目录路径
	protected String baseDir = "";
	// 文件保存相对顶级目录的路径
	protected String relativeDir = "";
	// 文件临时路径
	private String tempdir = "";
	// 最大文件大小
	private long maxFileSize = 0L;
	// 最大缓冲区大小
	protected int maxMemSize = 0;
	// 允许上传的类型
	protected String[] allowType = null;
	// 不允许上传的类型
	protected String[] denyType = null;
	// 是否为绝对路径
	protected boolean isAbsoluteDir = false;
	// 设置上传文件总量的最大值
	protected long maxSize = 0L;
	protected String downloadBaseUrl = "";
	protected String downFunPath = IFileConfiguration.DEFAULT_DOWNLOAD_BASE_URL;
	public DefaultFileConfiguration() {
		super();
	}

	public DefaultFileConfiguration(String configFilePath) {
		super();
		this.configFilePath = configFilePath;
	}

	public void init() throws Exception{
		load(DEFAULT_CONFIG_PATH);
		load(configFilePath);
	}

	public String setBaseDir(String baseDir){
		if(StringUtils.isNotBlank(baseDir)){
			this.baseDir = baseDir;
		}
		return baseDir;
	}

	public String getBaseUrl(HttpServletRequest request){
		String downloadBaseUrl = configInfo.get(Global.BASEURL);
		if (StringUtils.isBlank(downloadBaseUrl)) {
			downloadBaseUrl = HttpUtils.getBasePath(request);
		}
		return downloadBaseUrl;
	}
	
	private String getDownloadBaseUrl(HttpServletRequest request,String downFunPath){
		String downloadBaseUrl = configInfo.get(Global.BASEURL);
		if (StringUtils.isBlank(downloadBaseUrl)) {
			downloadBaseUrl = HttpUtils.getBasePath(request) + downFunPath;
		}
		return downloadBaseUrl;
	}
	
	
	/**
	 * A 初始化文件限制对象
	 * 
	 * @author lisheng 2014年2月21日 下午8:26:49
	 * @throws Exception 
	 */
	private void intFileLimit(ServletContext cervletContext, Map<String,String> map) throws Exception {
		String rootDir = cervletContext.getRealPath("/");
		this.setRootDir(rootDir);
		if(map==null){
			return;
		}
		String baseDir = map.get(Global.baseDir);
		if (!StringUtils.isBlank(baseDir)) {
			this.setBaseDir(baseDir);
		}
		String tempdir = map.get(Global.tempdir);
		if (!StringUtils.isBlank(tempdir)) {
			this.setTempdir(tempdir);
		}
		String maxFileSize = map.get(Global.maxFileSize);
		if (!StringUtils.isBlank(maxFileSize)) {
			try {
				long size = SizeValue.parseSizeValue(maxFileSize).singles();
				if (size > MAX_SIZE) {
					size = MAX_SIZE;
				}
				this.setMaxFileSize(size);
			} catch (Exception e) {
				this.logger.info(e.getMessage(), e);
			}
		}
		String allowType = map.get(Global.allowType);
		if (!StringUtils.isBlank(allowType)) {
			this.setAllowType(this.getType(allowType));
		}
		
		String denyType = map.get(Global.denyType);
		if (!StringUtils.isBlank(denyType)) {
			this.setDenyType(this.getType(denyType));
		}
		// 私定
		String _isAbsolutePath = map.get(Global.isAbsolutePath);
		baseDir = this.handlPara(map, baseDir, _isAbsolutePath);
		this.setBaseDir(baseDir);
		this.setAbsoluteDir(this.isAbsoluteDir);

		this.logger.info(this.toString());
	}
	
	/**
	 * 处理参数
	 * 
	 * @author lisheng
	 * @date 2015年10月16日 下午9:36:40
	 * @version V1.0
	 * @return
	 */
	private String handlPara(Map<String,String> servletContext, String _baseDir,
			String _isAbsolutePath) {
		String baseDir = _baseDir;
		if (!StringUtils.isBlank(_isAbsolutePath)) {
			try {
				if ("true".equalsIgnoreCase(_isAbsolutePath)) {
					this.isAbsoluteDir = true;
				}
			} catch (Exception e) {
				this.logger.info(e.getMessage(), e);
			}
		}
		if (StringUtils.isBlank(baseDir)) {
			return "";
		}
		if (!this.isAbsoluteDir && !StringUtils.isBlank(baseDir)) {
			// 设置文件上传路径
			String dir = baseDir;
			int index = 0;
			while (dir.startsWith("/")) {
				dir = dir.replaceFirst("/", "");
			}
			while (dir.startsWith("\\")) {
				dir = dir.replaceFirst("\\\\", "");
			}
			while (dir.startsWith("../")) {
				dir = dir.replaceFirst("../", "");
				index++;
			}
			while (dir.startsWith("..\\")) {
				dir = dir.replaceFirst("..\\\\", "");
				index++;
			}
			String upload = "";
			if (index > 0) {
				// this.isAbsolutePath = true ;
				upload = this.getRootDir();
				while (index > 0) {
					File f = new File(upload);
					upload = f.getParent();
					index--;
				}
				upload = upload + File.separator + dir;
			} else {
				upload = this.getRootDir()+File.separator + dir;
			}
			baseDir = upload;
		}
		if (StringUtils.isBlank(baseDir)) {
			baseDir = this.getRootDir();
		}
		baseDir = FileUtil.toLocalSeparator(baseDir);
		this.logger.info("上传文件保存目录:" + baseDir);
		this.logger.info("是否为绝对路径:" + isAbsoluteDir);
		return FileUtil.mkDirIfNotExist(baseDir);
	}
	

	/**
	 * 获取文件类型
	 * 
	 * @author lisheng
	 * @date 2015年10月16日 下午9:36:18
	 * @version V1.0
	 * @param type
	 * @return
	 */
	private String[] getType(final String type) {
		String[] strs = null;
		if (!StringUtils.isBlank(type)) {
			strs = type.split(",");
		}
		return strs;
	}

	/**
	 * 
	 * @author lisheng
	 * @date 2016年4月28日 下午10:30:52
	 * @version V1.0
	 * @param name
	 */
	private void load(String name) {
		LinkedHashMap<String, String> map1;
		try {
			logger.info("开始加载" + name);
			map1 = PropertyUtil.toLinkedMap(name);
			if (map1 != null) {
				configInfo.putAll(map1);
			}
			logger.info("加载数据：" + map1);
		} catch (FileNotFoundException e1) {
			logger.error("加载" + name + "出错!", e1);
		} catch (IOException e1) {
			logger.error("加载" + name + "出错!", e1);
		}
	}

	public String getConfigFilePath() {
		return this.configFilePath;
	}

	public void setConfigFilePath(String configFilePath) {
		this.configFilePath = configFilePath;
	}

	public String getBaseUrl() {
		return this.baseUrl;
	}

	public void setBaseUrl(String baseUrl) {
		this.baseUrl = baseUrl;
	}

	public String getRootDir() {
		return this.rootDir;
	}

	public void setRootDir(String rootDir) {
		this.rootDir = rootDir;
	}

	public String getBaseDir() {
		return this.baseDir;
	}

	public String getRelativeDir() {
		return this.relativeDir;
	}

	public void setRelativeDir(String relativeDir) {
		this.relativeDir = relativeDir;
	}

	public String getTempdir() {
		return this.tempdir;
	}

	public void setTempdir(String tempdir) {
		this.tempdir = tempdir;
	}

	public long getMaxFileSize() {
		return this.maxFileSize;
	}

	public void setMaxFileSize(long maxFileSize) {
		this.maxFileSize = maxFileSize;
	}

	public int getMaxMemSize() {
		return this.maxMemSize;
	}

	public void setMaxMemSize(int maxMemSize) {
		this.maxMemSize = maxMemSize;
	}

	public String[] getAllowType() {
		return this.allowType;
	}

	public void setAllowType(String[] allowType) {
		this.allowType = allowType;
	}

	public String[] getDenyType() {
		return this.denyType;
	}

	public void setDenyType(String[] denyType) {
		this.denyType = denyType;
	}

	public boolean isAbsoluteDir() {
		return this.isAbsoluteDir;
	}

	public void setAbsoluteDir(boolean isAbsoluteDir) {
		this.isAbsoluteDir = isAbsoluteDir;
	}

	public long getMaxSize() {
		return this.maxSize;
	}

	public void setMaxSize(long maxSize) {
		this.maxSize = maxSize;
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("DefaultFileConfiguration [configFilePath=");
		builder.append(this.configFilePath);
		builder.append(", baseUrl=");
		builder.append(this.baseUrl);
		builder.append(", rootDir=");
		builder.append(this.rootDir);
		builder.append(", baseDir=");
		builder.append(this.baseDir);
		builder.append(", relativeDir=");
		builder.append(this.relativeDir);
		builder.append(", tempdir=");
		builder.append(this.tempdir);
		builder.append(", maxFileSize=");
		builder.append(this.maxFileSize);
		builder.append(", maxMemSize=");
		builder.append(this.maxMemSize);
		builder.append(", allowType=");
		builder.append(Arrays.toString(this.allowType));
		builder.append(", denyType=");
		builder.append(Arrays.toString(this.denyType));
		builder.append(", isAbsoluteDir=");
		builder.append(this.isAbsoluteDir);
		builder.append(", maxSize=");
		builder.append(this.maxSize);
		builder.append("]");
		return builder.toString();
	}
	/**
	 * 获取下载文件根路径
	 * @author lisheng
	 * @date 2016年4月27日 下午8:30:40
	 * @version V1.0
	 * @param request
	 * @return
	 */ 
	@Override
	public String getDownloadBaseUrl(HttpServletRequest request) {
		if(StringUtils.isBlank(baseUrl)){
			baseUrl = this.getDownloadBaseUrl(request, this.downFunPath);
		}
		return baseUrl;
	}
	
	@Override
	public String setDownloadFunPath(String downFunPath) {
		this.downFunPath = downFunPath;
		return downFunPath;
	}

	@Override
	public String setAppendBaseDir(String baseDir) {
		this.baseDir = this.baseDir+File.separator+baseDir;
		return this.baseDir;
	}

	@Override
	public void setServletContext(ServletContext servletContext) {
		try {
			this.init();
			intFileLimit(servletContext,configInfo);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
